"""
Jenkins配置XML生成器
支持完整的Jenkins任务配置
"""
import logging

logger = logging.getLogger(__name__)


class JenkinsConfigGenerator:
    """Jenkins配置XML生成器"""
    
    def generate_job_config_xml(self, job):
        """根据任务类型生成Jenkins配置XML"""
        if job.job_type == 'freestyle':
            return self.generate_freestyle_config(job)
        elif job.job_type == 'maven':
            return self.generate_maven_config(job)
        elif job.job_type == 'pipeline':
            return self.generate_pipeline_config(job)
        else:
            return self.generate_freestyle_config(job)  # 默认使用freestyle

    def generate_freestyle_config(self, job):
        """生成Freestyle项目配置XML"""
        config = job.config_json or {}
        
        # 基本配置
        disabled = config.get('disabled', False)
        concurrent_build = config.get('concurrent_build', False)
        quiet_period = config.get('quiet_period', 5)
        
        # 源码管理配置
        scm_type = config.get('scm_type', 'none')
        git_url = config.get('git_url', '')
        git_branch = config.get('git_branch', 'main')
        git_credentials = config.get('git_credentials', '')
        
        # 构建触发器配置
        triggers = config.get('triggers', {})
        
        # 构建环境配置
        build_env = config.get('build_environment', {})
        
        # 构建步骤
        build_steps = config.get('build_steps', [])
        
        # 构建后操作
        post_build = config.get('post_build_actions', {})
        
        # 生成各部分配置
        scm_xml = self.generate_scm_xml(scm_type, git_url, git_branch, git_credentials)
        triggers_xml = self.generate_triggers_xml(triggers)
        build_wrappers_xml = self.generate_build_wrappers_xml(build_env)
        builders_xml = self.generate_builders_xml(build_steps, job)
        publishers_xml = self.generate_publishers_xml(post_build)
        properties_xml = self.generate_properties_xml(config)

        config_xml = f"""<?xml version='1.1' encoding='UTF-8'?>
<project>
  <actions/>
  <description>{job.description or ''}</description>
  <keepDependencies>false</keepDependencies>
  {properties_xml}
  {scm_xml}
  <canRoam>true</canRoam>
  <disabled>{str(disabled).lower()}</disabled>
  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
  {triggers_xml}
  <concurrentBuild>{str(concurrent_build).lower()}</concurrentBuild>
  <quietPeriod>{quiet_period}</quietPeriod>
  {builders_xml}
  {publishers_xml}
  {build_wrappers_xml}
</project>"""
        return config_xml

    def generate_scm_xml(self, scm_type, git_url, git_branch, git_credentials):
        """生成源码管理配置XML"""
        if scm_type == 'git' and git_url:
            credentials_xml = ""
            if git_credentials:
                credentials_xml = f"<credentialsId>{git_credentials}</credentialsId>"
            
            return f"""<scm class="hudson.plugins.git.GitSCM" plugin="git@4.8.3">
    <configVersion>2</configVersion>
    <userRemoteConfigs>
      <hudson.plugins.git.UserRemoteConfig>
        <url>{git_url}</url>
        {credentials_xml}
      </hudson.plugins.git.UserRemoteConfig>
    </userRemoteConfigs>
    <branches>
      <hudson.plugins.git.BranchSpec>
        <name>*/{git_branch}</name>
      </hudson.plugins.git.BranchSpec>
    </branches>
    <doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
    <submoduleCfg class="list"/>
    <extensions/>
  </scm>"""
        else:
            return "<scm class=\"hudson.scm.NullSCM\"/>"

    def generate_triggers_xml(self, triggers):
        """生成构建触发器配置XML"""
        trigger_list = []
        
        # SCM轮询
        if triggers.get('scm_polling') and triggers.get('scm_schedule'):
            trigger_list.append(f"""<hudson.triggers.SCMTrigger>
      <spec>{triggers['scm_schedule']}</spec>
      <ignorePostCommitHooks>false</ignorePostCommitHooks>
    </hudson.triggers.SCMTrigger>""")
        
        # 定时构建
        if triggers.get('build_periodically') and triggers.get('build_schedule'):
            trigger_list.append(f"""<hudson.triggers.TimerTrigger>
      <spec>{triggers['build_schedule']}</spec>
    </hudson.triggers.TimerTrigger>""")
        
        # GitHub Hook
        if triggers.get('github_hook'):
            trigger_list.append("""<com.cloudbees.jenkins.GitHubPushTrigger plugin="github@1.34.1">
      <spec></spec>
    </com.cloudbees.jenkins.GitHubPushTrigger>""")
        
        if trigger_list:
            return f"<triggers>\n    {chr(10).join(trigger_list)}\n  </triggers>"
        else:
            return "<triggers/>"

    def generate_build_wrappers_xml(self, build_env):
        """生成构建环境配置XML"""
        wrapper_list = []
        
        # 删除工作空间
        if build_env.get('delete_workspace'):
            wrapper_list.append("""<hudson.plugins.ws__cleanup.PreBuildCleanup plugin="ws-cleanup@0.39">
      <deleteDirs>false</deleteDirs>
      <cleanupParameter></cleanupParameter>
      <externalDelete></externalDelete>
      <disableDeferredWipeout>false</disableDeferredWipeout>
    </hudson.plugins.ws__cleanup.PreBuildCleanup>""")
        
        # 添加时间戳
        if build_env.get('add_timestamps'):
            wrapper_list.append("""<hudson.plugins.timestamper.TimestamperBuildWrapper plugin="timestamper@1.13"/>""")
        
        # 构建超时
        if build_env.get('timeout_enabled'):
            timeout_minutes = build_env.get('timeout_minutes', 20)
            wrapper_list.append(f"""<hudson.plugins.build__timeout.BuildTimeoutWrapper plugin="build-timeout@1.24">
      <strategy class="hudson.plugins.build_timeout.impl.AbsoluteTimeOutStrategy">
        <timeoutMinutes>{timeout_minutes}</timeoutMinutes>
      </strategy>
      <operationList/>
    </hudson.plugins.build__timeout.BuildTimeoutWrapper>""")
        
        if wrapper_list:
            return f"<buildWrappers>\n    {chr(10).join(wrapper_list)}\n  </buildWrappers>"
        else:
            return "<buildWrappers/>"

    def generate_builders_xml(self, build_steps, job):
        """生成构建步骤配置XML"""
        if not build_steps:
            # 默认构建步骤
            default_command = f"""echo "构建开始"
echo "项目: {job.project.name}"
echo "环境: {job.environment.name}"
echo "构建完成\""""
            return f"""<builders>
    <hudson.tasks.Shell>
      <command>{default_command}</command>
    </hudson.tasks.Shell>
  </builders>"""
        
        builder_list = []
        for step in build_steps:
            step_type = step.get('type', 'shell')
            if step_type == 'shell':
                command = step.get('command', '')
                builder_list.append(f"""<hudson.tasks.Shell>
      <command>{command}</command>
    </hudson.tasks.Shell>""")
            elif step_type == 'batch':
                command = step.get('command', '')
                builder_list.append(f"""<hudson.tasks.BatchFile>
      <command>{command}</command>
    </hudson.tasks.BatchFile>""")
        
        if builder_list:
            return f"<builders>\n    {chr(10).join(builder_list)}\n  </builders>"
        else:
            return "<builders/>"

    def generate_publishers_xml(self, post_build):
        """生成构建后操作配置XML"""
        publisher_list = []
        
        # 归档构件
        if post_build.get('archive_artifacts'):
            artifacts = post_build['archive_artifacts']
            publisher_list.append(f"""<hudson.tasks.ArtifactArchiver>
      <artifacts>{artifacts}</artifacts>
      <allowEmptyArchive>false</allowEmptyArchive>
      <onlyIfSuccessful>false</onlyIfSuccessful>
      <fingerprint>false</fingerprint>
      <defaultExcludes>true</defaultExcludes>
      <caseSensitive>true</caseSensitive>
    </hudson.tasks.ArtifactArchiver>""")
        
        # JUnit测试结果
        if post_build.get('junit_results'):
            test_results = post_build['junit_results']
            publisher_list.append(f"""<hudson.tasks.junit.JUnitResultArchiver plugin="junit@1.48">
      <testResults>{test_results}</testResults>
      <keepLongStdio>false</keepLongStdio>
      <healthScaleFactor>1.0</healthScaleFactor>
      <allowEmptyResults>false</allowEmptyResults>
    </hudson.tasks.junit.JUnitResultArchiver>""")
        
        # 邮件通知
        if post_build.get('email_notification'):
            recipients = post_build.get('email_recipients', '')
            publisher_list.append(f"""<hudson.tasks.Mailer plugin="mailer@1.34">
      <recipients>{recipients}</recipients>
      <dontNotifyEveryUnstableBuild>false</dontNotifyEveryUnstableBuild>
      <sendToIndividuals>false</sendToIndividuals>
    </hudson.tasks.Mailer>""")
        
        if publisher_list:
            return f"<publishers>\n    {chr(10).join(publisher_list)}\n  </publishers>"
        else:
            return "<publishers/>"

    def generate_properties_xml(self, config):
        """生成属性配置XML"""
        property_list = []
        
        # 构建保留策略
        days_to_keep = config.get('days_to_keep', -1)
        num_to_keep = config.get('num_to_keep', -1)
        artifact_days_to_keep = config.get('artifact_days_to_keep', -1)
        artifact_num_to_keep = config.get('artifact_num_to_keep', -1)
        
        if any([days_to_keep > 0, num_to_keep > 0, artifact_days_to_keep > 0, artifact_num_to_keep > 0]):
            property_list.append(f"""<jenkins.model.BuildDiscarderProperty>
      <strategy class="hudson.tasks.LogRotator">
        <daysToKeep>{days_to_keep}</daysToKeep>
        <numToKeep>{num_to_keep}</numToKeep>
        <artifactDaysToKeep>{artifact_days_to_keep}</artifactDaysToKeep>
        <artifactNumToKeep>{artifact_num_to_keep}</artifactNumToKeep>
      </strategy>
    </jenkins.model.BuildDiscarderProperty>""")
        
        # 参数化构建
        parameters = config.get('parameters', [])
        if parameters:
            param_list = []
            for param in parameters:
                param_type = param.get('type', 'string')
                param_name = param.get('name', '')
                param_default = param.get('default_value', '')
                param_description = param.get('description', '')
                
                if param_type == 'string':
                    param_list.append(f"""<hudson.model.StringParameterDefinition>
          <name>{param_name}</name>
          <description>{param_description}</description>
          <defaultValue>{param_default}</defaultValue>
          <trim>false</trim>
        </hudson.model.StringParameterDefinition>""")
                elif param_type == 'boolean':
                    param_list.append(f"""<hudson.model.BooleanParameterDefinition>
          <name>{param_name}</name>
          <description>{param_description}</description>
          <defaultValue>{str(param_default).lower()}</defaultValue>
        </hudson.model.BooleanParameterDefinition>""")
                elif param_type == 'choice':
                    choices = param.get('choices', [])
                    choices_xml = '\n'.join([f'<string>{choice}</string>' for choice in choices])
                    param_list.append(f"""<hudson.model.ChoiceParameterDefinition>
          <name>{param_name}</name>
          <description>{param_description}</description>
          <choices class="java.util.Arrays$ArrayList">
            <a class="string-array">
              {choices_xml}
            </a>
          </choices>
        </hudson.model.ChoiceParameterDefinition>""")
            
            if param_list:
                property_list.append(f"""<hudson.model.ParametersDefinitionProperty>
      <parameterDefinitions>
        {chr(10).join(param_list)}
      </parameterDefinitions>
    </hudson.model.ParametersDefinitionProperty>""")
        
        if property_list:
            return f"<properties>\n    {chr(10).join(property_list)}\n  </properties>"
        else:
            return "<properties/>"

    def generate_maven_config(self, job):
        """生成Maven项目配置XML"""
        config = job.config_json or {}
        
        # Maven特定配置
        maven_name = config.get('maven_name', 'Maven')
        pom_file = config.get('pom_file', 'pom.xml')
        goals = config.get('maven_goals', 'clean compile package')
        maven_opts = config.get('maven_opts', '')
        
        # 基础配置与freestyle类似
        disabled = config.get('disabled', False)
        concurrent_build = config.get('concurrent_build', False)
        quiet_period = config.get('quiet_period', 5)
        
        # 源码管理配置
        scm_type = config.get('scm_type', 'none')
        git_url = config.get('git_url', '')
        git_branch = config.get('git_branch', 'main')
        git_credentials = config.get('git_credentials', '')
        
        # 构建触发器配置
        triggers = config.get('triggers', {})
        
        # 构建环境配置
        build_env = config.get('build_environment', {})
        
        # 构建后操作
        post_build = config.get('post_build_actions', {})
        
        # 生成各部分配置
        scm_xml = self.generate_scm_xml(scm_type, git_url, git_branch, git_credentials)
        triggers_xml = self.generate_triggers_xml(triggers)
        build_wrappers_xml = self.generate_build_wrappers_xml(build_env)
        publishers_xml = self.generate_publishers_xml(post_build)
        properties_xml = self.generate_properties_xml(config)

        config_xml = f"""<?xml version='1.1' encoding='UTF-8'?>
<maven2-moduleset plugin="maven-plugin@3.8">
  <actions/>
  <description>{job.description or ''}</description>
  <keepDependencies>false</keepDependencies>
  {properties_xml}
  {scm_xml}
  <canRoam>true</canRoam>
  <disabled>{str(disabled).lower()}</disabled>
  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
  {triggers_xml}
  <concurrentBuild>{str(concurrent_build).lower()}</concurrentBuild>
  <quietPeriod>{quiet_period}</quietPeriod>
  <rootModule>
    <groupId></groupId>
    <artifactId></artifactId>
  </rootModule>
  <goals>{goals}</goals>
  <mavenName>{maven_name}</mavenName>
  <mavenOpts>{maven_opts}</mavenOpts>
  <aggregatorStyleBuild>true</aggregatorStyleBuild>
  <incrementalBuild>false</incrementalBuild>
  <ignoreUpstremChanges>false</ignoreUpstremChanges>
  <ignoreUnsuccessfulUpstreams>false</ignoreUnsuccessfulUpstreams>
  <archivingDisabled>false</archivingDisabled>
  <siteArchivingDisabled>false</siteArchivingDisabled>
  <fingerprintingDisabled>false</fingerprintingDisabled>
  <resolveDependencies>false</resolveDependencies>
  <processPlugins>false</processPlugins>
  <mavenValidationLevel>-1</mavenValidationLevel>
  <runHeadless>false</runHeadless>
  <disableTriggerDownstreamProjects>false</disableTriggerDownstreamProjects>
  <blockTriggerWhenBuilding>true</blockTriggerWhenBuilding>
  <settings class="jenkins.mvn.DefaultSettingsProvider"/>
  <globalSettings class="jenkins.mvn.DefaultGlobalSettingsProvider"/>
  {publishers_xml}
  {build_wrappers_xml}
</maven2-moduleset>"""
        return config_xml

    def generate_pipeline_config(self, job):
        """生成Pipeline项目配置XML"""
        config = job.config_json or {}
        
        # Pipeline脚本
        pipeline_script = config.get('pipeline_script', '')
        if not pipeline_script:
            # 默认Pipeline脚本
            pipeline_script = f"""pipeline {{
    agent any

    stages {{
        stage('Checkout') {{
            steps {{
                echo '检出代码'
                // git branch: 'main', url: 'your-git-url'
            }}
        }}

        stage('Build') {{
            steps {{
                echo '构建项目: {job.project.name}'
                echo '环境: {job.environment.name}'
            }}
        }}

        stage('Test') {{
            steps {{
                echo '运行测试'
            }}
        }}

        stage('Deploy') {{
            steps {{
                echo '部署到 {job.environment.name} 环境'
            }}
        }}
    }}

    post {{
        always {{
            echo '构建完成'
        }}
    }}
}}"""

        disabled = config.get('disabled', False)
        concurrent_build = config.get('concurrent_build', False)
        quiet_period = config.get('quiet_period', 5)
        
        # 构建触发器配置
        triggers = config.get('triggers', {})
        triggers_xml = self.generate_triggers_xml(triggers)
        
        # 属性配置
        properties_xml = self.generate_properties_xml(config)

        config_xml = f"""<?xml version='1.1' encoding='UTF-8'?>
<flow-definition plugin="workflow-job@2.40">
  <actions/>
  <description>{job.description or ''}</description>
  <keepDependencies>false</keepDependencies>
  {properties_xml}
  <definition class="org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition" plugin="workflow-cps@2.92">
    <script>{pipeline_script}</script>
    <sandbox>true</sandbox>
  </definition>
  {triggers_xml}
  <disabled>{str(disabled).lower()}</disabled>
  <quietPeriod>{quiet_period}</quietPeriod>
</flow-definition>"""
        return config_xml
